package ai.people.netmon.auth.service;

import ai.people.core.grpc.lib.user.LoginRequest;
import ai.people.core.grpc.lib.user.LoginResponse;
import ai.people.core.grpc.lib.user.UserServiceGrpc;
import ai.people.core.security.entity.AuthenticationUser;
import ai.people.netmon.framework.constant.OAuth2Constant;
import ai.people.netmon.framework.domain.system.vo.NmSystemLoginUserVO;
import ai.people.netmon.framework.domain.system.vo.NmSystemRoleVO;
import ai.people.netmon.framework.domain.system.vo.NmSystemUserMenu;
import ai.people.netmon.framework.domain.system.vo.NmSystemUserVO;
import ai.people.netmon.utils.StringPool;
import com.alibaba.fastjson.JSON;
import com.google.protobuf.Empty;
import com.google.protobuf.Int64Value;
import lombok.extern.slf4j.Slf4j;
import net.devh.boot.grpc.client.inject.GrpcClient;
import org.apache.skywalking.apm.toolkit.trace.Tag;
import org.apache.skywalking.apm.toolkit.trace.Tags;
import org.apache.skywalking.apm.toolkit.trace.Trace;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class UserDetailsServiceImpl implements UserDetailsService {


    /**
     * 用户服务阻塞存根
     */
    @GrpcClient(value = "NM-SERVICE-SYSTEM")
    private UserServiceGrpc.UserServiceBlockingStub userServiceBlockingStub;
    

    @Autowired
    private ClientDetailsService clientDetailsService;

    @Trace
    @Override
    @Tags({@Tag(key = "param",value = "arg[0]")})
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        ////取出身份，如果身份为空说明没有认证
        //Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        ////没有认证统一采用httpbasic认证，httpbasic中存储了client_id和client_secret，开始认证client_id和client_secret
        //if (authentication == null) {
        //    ClientDetails clientDetails = clientDetailsService.loadClientByClientId(username);
        //    if (clientDetails != null) {
        //        //密码
        //        String clientSecret = clientDetails.getClientSecret();
        //        return new User(username, clientSecret, AuthorityUtils.commaSeparatedStringToAuthorityList(StringPool.EMPTY));
        //    }
        //}
        //if (StringUtils.isEmpty(username)) {
        //    return null;
        //}

        LoginResponse loginResponse = userServiceBlockingStub.loginUserInfo(LoginRequest.newBuilder().setUsername(username).build());
        NmSystemLoginUserVO nmSystemLoginUserVO = JSON.parseObject(loginResponse.getData(), NmSystemLoginUserVO.class);
        NmSystemUserVO nmSystemUserVO = nmSystemLoginUserVO.getNmSystemUserVO();
        List<NmSystemRoleVO> nmSystemRole = nmSystemLoginUserVO.getNmSystemRole();
        List<Long> roleIds = nmSystemRole.stream().map(NmSystemRoleVO::getId).collect(Collectors.toList());
        List<NmSystemUserMenu> nmSystemMenu = nmSystemLoginUserVO.getNmSystemMenu();
        List<String> roleCodes = nmSystemRole.stream().map(NmSystemRoleVO::getCode).collect(Collectors.toList());
        List<String> permission = nmSystemMenu.stream().map(NmSystemUserMenu::getPerms).collect(Collectors.toList());
        roleCodes.forEach(roleCode -> permission.add(OAuth2Constant.DEFAULT_ROLE_PREFIX + roleCode));
        String permissions = String.join(StringPool.COMMA, permission);
        AuthenticationUser authenticationUser = new AuthenticationUser(nmSystemUserVO.getId(), roleIds, roleCodes, nmSystemUserVO.getAccount(), nmSystemUserVO.getPhone(), nmSystemUserVO.getPassword(),
                nmSystemUserVO.getJoinMaxCount(), nmSystemUserVO.getLabel(), nmSystemUserVO.getPlace(), AuthorityUtils.commaSeparatedStringToAuthorityList(permissions));
        Empty empty = userServiceBlockingStub.updateLastLoginTime(Int64Value.of(authenticationUser.getUserId()));
        return authenticationUser;
    }
}
